
#include <windows.h>
#include "CDXEffect.h"
#include "CReleaseMacro.h"
#include <wchar.h>
#include <D3DX11async.h>
#include <assert.h>
#include "CCommIOFunc.h"
#include "Shlwapi.h"
#include <string>
#include <math.h>
extern HMODULE GetModule();
std::map<std::wstring, ID3D10Blob*> CDXEffect::ms_shaderCache;
CDXEffect::CDXEffect(CDXDevice* pDevice) : CDXBase(pDevice)
{
	m_pEffect = NULL;
	m_pEffectBuffer = NULL;
	m_nResourceLockedCount = 0;
}
CDXEffect::~CDXEffect()
{
	SAFE_RELEASE(m_pEffect);
	SAFE_RELEASE(m_pEffectBuffer);
	_ClearStoredResources();
}
HRESULT CDXEffect::_CompileShaderFromFile(LPCWSTR szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut )
{
	if (szFileName == NULL || szShaderModel == NULL || ppBlobOut == NULL)
	{
		return E_FAIL;
	}
	HRESULT hr = S_OK;
	// find the file
	std::wstring path = L"";
	
	
	std::vector<std::wstring> candPath;
	std::wstring localPath = szFileName;
	GetCandidateAbsPath(candPath, localPath);
	
	std::wstring strOrgPath = candPath[0];
	std::wstring strDllPath = candPath[1];
	std::wstring strExePath = candPath[2];
	std::wstring strArr[] = {strOrgPath, strDllPath, strExePath};
	for (int i =0; i < ARRAYSIZE(strArr); i++)
	{
		std::map<std::wstring, ID3DBlob*>::iterator iter;
		iter = ms_shaderCache.find(strArr[i]);
		if (iter != ms_shaderCache.end())
		{
			*ppBlobOut = iter->second;
			SAFE_ADDREF(*ppBlobOut);
			return S_OK;
		}
	}
	
	for (int i =0; i < 3; i++)
	{
		if (PathFileExistsW(strArr[i].c_str()))
		{
			path = strArr[i];
			break;
		}
	}

	DWORD dwShaderFlags = 0;
#if defined( DEBUG ) || defined( _DEBUG )
	// Set the D3D10_SHADER_DEBUG flag to embed debug information in the shaders.
	// Setting this flag improves the shader debugging experience, but still allows 
	// the shaders to be optimized and to run exactly the way they will run in 
	// the release configuration of this program.
	dwShaderFlags |= D3D10_SHADER_DEBUG;
#endif
	path += L"\0";
	ID3DBlob* pErrorBlob = NULL;
	hr = D3DX11CompileFromFile( path.c_str(), NULL, NULL, szEntryPoint, szShaderModel, 
		dwShaderFlags, 0, NULL, ppBlobOut, &pErrorBlob, NULL );

	if( FAILED(hr) )
	{
		if( pErrorBlob != NULL )
		{
			OutputDebugStringA( (char*)pErrorBlob->GetBufferPointer() );
			assert(0);
		}
		SAFE_RELEASE( pErrorBlob );
		return hr;
	}
	SAFE_RELEASE( pErrorBlob );
	std::wstring strPath = path;
	ms_shaderCache[strPath] = *ppBlobOut;
	return S_OK;

}
HRESULT CDXEffect::_LoadEffectFromFile(ID3D11Device* pDevice, LPCWSTR szFileName, ID3DBlob** ppEffectBuffer, ID3DX11Effect** ppEffect)
{
	if (pDevice == NULL)
		return E_FAIL;
	SAFE_RELEASE(*ppEffect);

	HRESULT hr = S_OK;
	char szShaderModel[MAX_PATH] = "fx_5_0";

	hr = _CompileShaderFromFile(szFileName, NULL, szShaderModel, ppEffectBuffer);
	if (*ppEffectBuffer == NULL)
	{
		return E_FAIL;
	}
	wcscpy_s(m_path, MAX_PATH, szFileName);

	hr = D3DX11CreateEffectFromMemory( (*ppEffectBuffer)->GetBufferPointer(),
		(*ppEffectBuffer)->GetBufferSize(), NULL, pDevice, ppEffect ) ;
	if (FAILED(hr))
		return hr;

	return hr;
}

HRESULT CDXEffect::_StoreResourceByName(CDXResource* pResource, std::string name)
{
	if (m_nResourceLockedCount)
	{
		assert(0);
		return E_FAIL;
	}
	std::map<std::string, std::vector<CDXResource*>>::iterator iter;
	iter = m_pResourceByName.find(name);
	if (iter != m_pResourceByName.end())
	{
		for (UINT i = 0; i < iter->second.size(); i++)
		{
			SAFE_RELEASE(iter->second[i]);
		}
		iter->second.clear();
		m_pResourceByName.erase(iter);
	}
	if (pResource == NULL)
	{
		return S_OK;
	}
	std::vector<CDXResource*> storeResource(1, pResource);
	SAFE_ADDREF(pResource);
	m_pResourceByName[name] = storeResource;
	return S_OK;
}
HRESULT CDXEffect::_StoreResourceByIndex(CDXResource* pResource, UINT index)
{
	if (m_nResourceLockedCount)
	{
		assert(0);
		return E_FAIL;
	}
	std::map<UINT,  std::vector<CDXResource*>>::iterator iter;
	iter = m_pResourceByIndex.find(index);
	if (iter != m_pResourceByIndex.end())
	{
		for (UINT i = 0; i < iter->second.size(); i++)
		{
			SAFE_RELEASE(iter->second[i]);
		}
		iter->second.clear();
		m_pResourceByIndex.erase(iter);
	}
	if (pResource == NULL)
	{
		return S_OK;
	}
	std::vector<CDXResource*> storeResource(1, pResource);
	SAFE_ADDREF(pResource);
	m_pResourceByIndex[index] = storeResource;
	return S_OK;
}
HRESULT CDXEffect::_StoreResourceBySemantic(CDXResource* pResource, std::string semantic)
{
	if (m_nResourceLockedCount)
	{
		assert(0);
		return E_FAIL;
	}
	std::map<std::string,  std::vector<CDXResource*>>::iterator iter;
	iter = m_pResourceBySemantic.find(semantic);
	if (iter != m_pResourceBySemantic.end())
	{
		for (UINT i = 0; i < iter->second.size(); i++)
		{
			SAFE_RELEASE(iter->second[i]);
		}
		iter->second.clear();
		m_pResourceBySemantic.erase(iter);
	}
	if (pResource == NULL)
	{
		return S_OK;
	}
	std::vector<CDXResource*> storeResource(1, pResource);
	SAFE_ADDREF(pResource);
	m_pResourceBySemantic[semantic] = storeResource;
	return S_OK;
}
HRESULT CDXEffect::_StoreResourceArrayByName(std::vector<CDXResource*> pResources, std::string name)
{
	if (m_nResourceLockedCount)
	{
		assert(0);
		return E_FAIL;
	}
	std::map<std::string,  std::vector<CDXResource*>>::iterator iter;
	iter = m_pResourceByName.find(name);
	if (iter != m_pResourceByName.end())
	{
		for (UINT i = 0; i < iter->second.size(); i++)
		{
			SAFE_RELEASE(iter->second[i]);
		}
		iter->second.clear();
		m_pResourceByName.erase(iter);
	}
	if (pResources.size() == 0)
	{
		return S_OK;
	}

	m_pResourceByName[name] = pResources;
	for (UINT i =0; i < pResources.size(); i++)
	{
		SAFE_ADDREF(pResources[i]);
	}
	return S_OK;
}
HRESULT CDXEffect::_StoreResourceArrayByIndex(std::vector<CDXResource*> pResources, UINT index)
{
	if (m_nResourceLockedCount)
	{
		assert(0);
		return E_FAIL;
	}
	std::map<UINT,  std::vector<CDXResource*>>::iterator iter;
	iter = m_pResourceByIndex.find(index);
	if (iter != m_pResourceByIndex.end())
	{
		for (UINT i = 0; i < iter->second.size(); i++)
		{
			SAFE_RELEASE(iter->second[i]);
		}
		iter->second.clear();
		m_pResourceByIndex.erase(iter);
	}
	if (pResources.size() == 0)
	{
		return S_OK;
	}

	m_pResourceByIndex[index] = pResources;
	for (UINT i =0; i < pResources.size(); i++)
	{
		SAFE_ADDREF(pResources[i]);
	}
	return S_OK;
}
HRESULT CDXEffect::_StoreResourceArrayBySemantic(std::vector<CDXResource*> pResources, std::string semantic)
{
	if (m_nResourceLockedCount)
	{
		assert(0);
		return E_FAIL;
	}
	std::map<std::string, std::vector<CDXResource*>>::iterator iter;
	iter = m_pResourceBySemantic.find(semantic);
	if (iter != m_pResourceBySemantic.end())
	{
		for (UINT i = 0; i < iter->second.size(); i++)
		{
			SAFE_RELEASE(iter->second[i]);
		}
		iter->second.clear();
		m_pResourceBySemantic.erase(iter);
	}
	if (pResources.size() == 0)
	{
		return S_OK;
	}

	m_pResourceBySemantic[semantic] = pResources;
	for (UINT i =0; i < pResources.size(); i++)
	{
		SAFE_ADDREF(pResources[i]);
	}
	return S_OK;
}
HRESULT CDXEffect::_ClearStoredResources()
{
	if (m_nResourceLockedCount)
	{
		assert(0);
		return E_FAIL;
	}
	std::map<std::string, std::vector<CDXResource*>>::iterator iterName;
	for (iterName = m_pResourceByName.begin(); iterName != m_pResourceByName.end(); iterName++)
	{
		for (UINT i =0; i < iterName->second.size(); i++)
		{
			SAFE_RELEASE(iterName->second[i]);
		}
		iterName->second.clear();
	}
	m_pResourceByName.clear();

	std::map<UINT, std::vector<CDXResource*>>::iterator iterIdx;
	for (iterIdx = m_pResourceByIndex.begin(); iterIdx != m_pResourceByIndex.end(); iterIdx++)
	{
		for (UINT i =0; i < iterIdx->second.size(); i++)
		{
			SAFE_RELEASE(iterIdx->second[i]);
		}
		iterIdx->second.clear();
	}
	m_pResourceByIndex.clear();

	std::map<std::string, std::vector<CDXResource*>>::iterator iterSemantic;
	for (iterSemantic = m_pResourceBySemantic.begin(); iterSemantic != m_pResourceBySemantic.end(); iterSemantic++)
	{
		for (UINT i =0; i < iterSemantic->second.size(); i++)
		{
			SAFE_RELEASE(iterSemantic->second[i]);
		}
		iterSemantic->second.clear();
	}
	m_pResourceBySemantic.clear();
	return S_OK;

}

HRESULT CDXEffect::LockKeyMutexResources()
{
	m_nResourceLockedCount++;
	std::map<std::string, std::vector<CDXResource*>>::iterator iterName;
	for (iterName = m_pResourceByName.begin(); iterName != m_pResourceByName.end(); iterName++)
	{
		for (UINT i =0; i < iterName->second.size(); i++)
		{
			iterName->second[i]->KeyMutex11Acquire();
		}
	}


	std::map<UINT, std::vector<CDXResource*>>::iterator iterIdx;
	for (iterIdx = m_pResourceByIndex.begin(); iterIdx != m_pResourceByIndex.end(); iterIdx++)
	{
		for (UINT i =0; i < iterIdx->second.size(); i++)
		{
			iterIdx->second[i]->KeyMutex11Acquire();
		}
	}
	

	std::map<std::string, std::vector<CDXResource*>>::iterator iterSemantic;
	for (iterSemantic = m_pResourceBySemantic.begin(); iterSemantic != m_pResourceBySemantic.end(); iterSemantic++)
	{
		for (UINT i =0; i < iterSemantic->second.size(); i++)
		{
			iterSemantic->second[i]->KeyMutex11Acquire();
		}
	}
	
	return S_OK;
}
HRESULT CDXEffect::UnLockKeyMutexResources()
{
	if (m_nResourceLockedCount == 0)
	{
		assert(0);
		return E_FAIL;
	}
	m_nResourceLockedCount--;
	std::map<std::string, std::vector<CDXResource*>>::iterator iterName;
	for (iterName = m_pResourceByName.begin(); iterName != m_pResourceByName.end(); iterName++)
	{
		for (UINT i =0; i < iterName->second.size(); i++)
		{
			iterName->second[i]->KeyMutex11Release();
		}
	}


	std::map<UINT, std::vector<CDXResource*>>::iterator iterIdx;
	for (iterIdx = m_pResourceByIndex.begin(); iterIdx != m_pResourceByIndex.end(); iterIdx++)
	{
		for (UINT i =0; i < iterIdx->second.size(); i++)
		{
			iterIdx->second[i]->KeyMutex11Release();
		}
	}


	std::map<std::string, std::vector<CDXResource*>>::iterator iterSemantic;
	for (iterSemantic = m_pResourceBySemantic.begin(); iterSemantic != m_pResourceBySemantic.end(); iterSemantic++)
	{
		for (UINT i =0; i < iterSemantic->second.size(); i++)
		{
			iterSemantic->second[i]->KeyMutex11Release();
		}
	}
	return S_OK;
}


ID3DX11Effect* CDXEffect::GetEffect()
{
	return m_pEffect;
}
HRESULT CDXEffect::SetEffect(ID3DX11Effect* pEffect)
{
	if (pEffect == NULL)
		return E_FAIL;
	SAFE_RELEASE(m_pEffect);
	SAFE_RELEASE(m_pEffectBuffer);
	swprintf(m_path, MAX_PATH, L"");
	m_pEffect = pEffect;
	SAFE_ADDREF(m_pEffect);
	return S_OK;
}
ID3DBlob* CDXEffect::GetEffectBuffer()
{
	return m_pEffectBuffer;
}
HRESULT CDXEffect::LoadFromFile(LPCWSTR szFileName)
{
	if (m_pDevice == NULL)
		return E_FAIL;
	SAFE_RELEASE(m_pEffect);
	SAFE_RELEASE(m_pEffectBuffer);
	ID3D11Device* pDX11Device = m_pDevice->GetD3D11Device();
	return _LoadEffectFromFile(pDX11Device, szFileName, &m_pEffectBuffer, &m_pEffect);
}

HRESULT CDXEffect::SetVariableByName(const char* varName, void* pValue, UINT offset, UINT nByte)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	ID3DX11EffectVariable* pVaiable = m_pEffect->GetVariableByName(varName);
	if (!pVaiable->IsValid())
		return E_FAIL;
	return pVaiable->SetRawValue(pValue, offset, nByte);
}
HRESULT CDXEffect::SetVariableBySemantic(const char* semantic, void* pValue, UINT offset, UINT nByte)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	ID3DX11EffectVariable* pVaiable = m_pEffect->GetVariableBySemantic(semantic);
	if (!pVaiable->IsValid())
		return E_FAIL;
	return pVaiable->SetRawValue(pValue, offset, nByte);
}
HRESULT CDXEffect::SetVariableByIndex(UINT idx, void* pValue, UINT offset, UINT nByte)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	ID3DX11EffectVariable* pVaiable = m_pEffect->GetVariableByIndex(idx);
	if (!pVaiable->IsValid())
		return E_FAIL;
	return pVaiable->SetRawValue(pValue, offset, nByte);
}


HRESULT CDXEffect::SetMatrixVariableByName(const char* varName, float* pMatrix, bool bTranspose)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectMatrixVariable* pVaiable = m_pEffect->GetVariableByName(varName)->AsMatrix();
	if (!pVaiable->IsValid())
		return E_FAIL;
	if (!bTranspose)
		hr = pVaiable->SetMatrix(pMatrix);
	else
		hr = pVaiable->SetMatrixTranspose(pMatrix);
	return hr;
}
HRESULT CDXEffect::SetMatrixVariableBySemantic(const char* semantic, float* pMatrix, bool bTranspose) 
{
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectMatrixVariable* pVaiable = m_pEffect->GetVariableBySemantic(semantic)->AsMatrix();
	if (!pVaiable->IsValid())
		return E_FAIL;
	if (!bTranspose)
		hr = pVaiable->SetMatrix(pMatrix);
	else
		hr = pVaiable->SetMatrixTranspose(pMatrix);
	return hr;
	
}
HRESULT CDXEffect::SetMatrixVariableByIndex(UINT idx, float* pMatrix, bool bTranspose)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectMatrixVariable* pVaiable = m_pEffect->GetVariableByIndex(idx)->AsMatrix();
	if (!pVaiable->IsValid())
		return E_FAIL;
	if (!bTranspose)
		hr = pVaiable->SetMatrix(pMatrix);
	else
		hr = pVaiable->SetMatrixTranspose(pMatrix);
	return hr;
}

HRESULT CDXEffect::SetMatrixArrayVariableByName(const char* varName, float* pMatrix, UINT offset, UINT nElem, bool bTranspose)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectMatrixVariable* pVaiable = m_pEffect->GetVariableByName(varName)->AsMatrix();
	if (!pVaiable->IsValid())
		return E_FAIL;
	if (!bTranspose)
		hr = pVaiable->SetMatrixArray(pMatrix, offset, nElem);
	else
		hr = pVaiable->SetMatrixTransposeArray(pMatrix, offset, nElem);
	return hr;
}
HRESULT CDXEffect::SetMatrixArrayVariableBySemantic(const char* semantic, float* pMatrix, UINT offset, UINT nElem, bool bTranspose)
{ 
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectMatrixVariable* pVaiable = m_pEffect->GetVariableBySemantic(semantic)->AsMatrix();
	if (!pVaiable->IsValid())
		return E_FAIL;
	if (!bTranspose)
		hr = pVaiable->SetMatrixArray(pMatrix, offset, nElem);
	else
		hr = pVaiable->SetMatrixTransposeArray(pMatrix, offset, nElem);
	return hr;	
}
HRESULT CDXEffect::SetMatrixArrayVariableByIndex(UINT idx, float* pMatrix, UINT offset, UINT nElem, bool bTranspose)
{ 
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectMatrixVariable* pVaiable = m_pEffect->GetVariableByIndex(idx)->AsMatrix();
	if (!pVaiable->IsValid())
		return E_FAIL;
	if (!bTranspose)
		hr = pVaiable->SetMatrixArray(pMatrix, offset, nElem);
	else
		hr = pVaiable->SetMatrixTransposeArray(pMatrix, offset, nElem);
	return hr;	
}

HRESULT CDXEffect::SetShaderResourceVariableByName(const char* varName, ID3D11ShaderResourceView* pSRV)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	ID3DX11EffectShaderResourceVariable* pVaiable = m_pEffect->GetVariableByName(varName)->AsShaderResource();
	if (!pVaiable->IsValid())
		return E_FAIL;
	return pVaiable->SetResource(pSRV);
}
HRESULT CDXEffect::SetShaderResourceVariableBySemantic(const char* semantic, ID3D11ShaderResourceView* pSRV)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	ID3DX11EffectShaderResourceVariable* pVaiable = m_pEffect->GetVariableBySemantic(semantic)->AsShaderResource();
	if (!pVaiable->IsValid())
		return E_FAIL;
	return pVaiable->SetResource(pSRV);
}
HRESULT CDXEffect::SetShaderResourceVariableByIndex(UINT idx, ID3D11ShaderResourceView* pSRV) 
{ 
	if (m_pEffect == NULL)
		return E_FAIL;
	ID3DX11EffectShaderResourceVariable* pVaiable = m_pEffect->GetVariableByIndex(idx)->AsShaderResource();
	if (!pVaiable->IsValid())
		return E_FAIL;
	return pVaiable->SetResource(pSRV);
}
HRESULT CDXEffect::SetShaderResourceVariableByName(const char* varName, CDXResource* pResource)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectShaderResourceVariable* pVaiable = m_pEffect->GetVariableByName(varName)->AsShaderResource();
	if (!pVaiable->IsValid())
		return E_FAIL;
	ID3D11ShaderResourceView* pSRV = NULL;
	hr = pResource->GetShaderResourceView(NULL, &pSRV);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	hr = _StoreResourceByName(pResource, std::string(varName));
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	return pVaiable->SetResource(pSRV);
}
HRESULT CDXEffect::SetShaderResourceVariableBySemantic(const char* semantic, CDXResource* pResource)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectShaderResourceVariable* pVaiable = m_pEffect->GetVariableBySemantic(semantic)->AsShaderResource();
	if (!pVaiable->IsValid())
		return E_FAIL;
	ID3D11ShaderResourceView* pSRV = NULL;
	hr = pResource->GetShaderResourceView(NULL, &pSRV);
	if (FAILED(hr))
		return hr;
	hr = _StoreResourceBySemantic(pResource, std::string(semantic));
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	return pVaiable->SetResource(pSRV);
}
HRESULT CDXEffect::SetShaderResourceVariableByIndex(UINT idx, CDXResource* pResource)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectShaderResourceVariable* pVaiable = m_pEffect->GetVariableByIndex(idx)->AsShaderResource();
	if (!pVaiable->IsValid())
		return E_FAIL;
	ID3D11ShaderResourceView* pSRV = NULL;
	hr = pResource->GetShaderResourceView(NULL, &pSRV);
	if (FAILED(hr))
		return hr;
	hr = _StoreResourceByIndex(pResource, idx);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	return pVaiable->SetResource(pSRV);
}

HRESULT CDXEffect::SetShaderResourceArrayVariableByName(const char* varName, ID3D11ShaderResourceView** ppSRV, UINT offset, UINT nElem)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	ID3DX11EffectShaderResourceVariable* pVaiable = m_pEffect->GetVariableByName(varName)->AsShaderResource();
	if (!pVaiable->IsValid())
		return E_FAIL;
	return pVaiable->SetResourceArray(ppSRV, offset, nElem);
}
HRESULT CDXEffect::SetShaderResourceArrayVariableBySemantic(const char* semantic, ID3D11ShaderResourceView** ppSRV, UINT offset, UINT nElem)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	ID3DX11EffectShaderResourceVariable* pVaiable = m_pEffect->GetVariableBySemantic(semantic)->AsShaderResource();
	if (!pVaiable->IsValid())
		return E_FAIL;
	return pVaiable->SetResourceArray(ppSRV, offset, nElem);
}
HRESULT CDXEffect::SetShaderResourceArrayVariableByIndex(UINT idx, ID3D11ShaderResourceView** ppSRV, UINT offset, UINT nElem)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	ID3DX11EffectShaderResourceVariable* pVaiable = m_pEffect->GetVariableByIndex(idx)->AsShaderResource();
	if (!pVaiable->IsValid())
		return E_FAIL;
	return pVaiable->SetResourceArray(ppSRV, offset, nElem);
}
HRESULT CDXEffect::SetShaderResourceArrayVariableByName(const char* varName, CDXResource** ppResource, UINT offset, UINT nElem)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectShaderResourceVariable* pVaiable = m_pEffect->GetVariableByName(varName)->AsShaderResource();
	if (!pVaiable->IsValid())
		return E_FAIL;
	ID3D11ShaderResourceView** ppSRV = new ID3D11ShaderResourceView*[nElem];
	std::vector<CDXResource*> resourceVec(nElem, NULL);
	for (UINT i=0; i < nElem; i++)
	{
		ID3D11ShaderResourceView* pSRV = NULL;
		hr = ppResource[i]->GetShaderResourceView(NULL, &pSRV);
		if (FAILED(hr))
		{
			SAFE_DELETE_ARRAY(ppSRV);
			return hr;
		}
		ppSRV[i] = pSRV;
		resourceVec[i] = ppResource[i];
	}
	hr = pVaiable->SetResourceArray(ppSRV, offset, nElem);
	SAFE_DELETE_ARRAY(ppSRV);
	_StoreResourceArrayByName(resourceVec, std::string(varName));
	return hr;
}
HRESULT CDXEffect::SetShaderResourceArrayVariableBySemantic(const char* semantic, CDXResource** ppResource, UINT offset, UINT nElem)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectShaderResourceVariable* pVaiable = m_pEffect->GetVariableBySemantic(semantic)->AsShaderResource();
	if (!pVaiable->IsValid())
		return E_FAIL;
	ID3D11ShaderResourceView** ppSRV = new ID3D11ShaderResourceView*[nElem];
	std::vector<CDXResource*> resourceVec(nElem, NULL);
	for (UINT i=0; i < nElem; i++)
	{
		ID3D11ShaderResourceView* pSRV = NULL;
		hr = ppResource[i]->GetShaderResourceView(NULL, &pSRV);
		if (FAILED(hr))
		{
			assert(0);
			SAFE_DELETE_ARRAY(ppSRV);
			return hr;
		}
		ppSRV[i] = pSRV;
		resourceVec[i] = ppResource[i];
	}

	hr = pVaiable->SetResourceArray(ppSRV, offset, nElem);
	SAFE_DELETE_ARRAY(ppSRV);
	_StoreResourceArrayBySemantic(resourceVec, std::string(semantic));
	return hr;
}
HRESULT CDXEffect::SetShaderResourceArrayVariableByIndex(UINT idx, CDXResource** ppResource, UINT offset, UINT nElem)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectShaderResourceVariable* pVaiable = m_pEffect->GetVariableByIndex(idx)->AsShaderResource();
	if (!pVaiable->IsValid())
		return E_FAIL;
	ID3D11ShaderResourceView** ppSRV = new ID3D11ShaderResourceView*[nElem];
	std::vector<CDXResource*> resourceVec(nElem, NULL);
	for (UINT i=0; i < nElem; i++)
	{
		ID3D11ShaderResourceView* pSRV = NULL;
		hr = ppResource[i]->GetShaderResourceView(NULL, &pSRV);
		if (FAILED(hr))
		{
			SAFE_DELETE_ARRAY(ppSRV);
			return hr;
		}
		ppSRV[i] = pSRV;
		resourceVec[i] = ppResource[i];
	}
	hr = pVaiable->SetResourceArray(ppSRV, offset, nElem);
	SAFE_DELETE_ARRAY(ppSRV);
	_StoreResourceArrayByIndex(resourceVec, idx);
	return hr;
}

HRESULT CDXEffect::SetUnorderAccessViewVariableByName(const char* varName, ID3D11UnorderedAccessView* pUAV)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectUnorderedAccessViewVariable* pVaiable = m_pEffect->GetVariableByName(varName)->AsUnorderedAccessView();
	if (!pVaiable->IsValid())
		return E_FAIL;
	return pVaiable->SetUnorderedAccessView(pUAV);
}
HRESULT CDXEffect::SetUnorderAccessViewVariableBySemantic(const char* semantic, ID3D11UnorderedAccessView* pUAV)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectUnorderedAccessViewVariable* pVaiable = m_pEffect->GetVariableBySemantic(semantic)->AsUnorderedAccessView();
	if (!pVaiable->IsValid())
		return E_FAIL;
	return pVaiable->SetUnorderedAccessView(pUAV);
}
HRESULT CDXEffect::SetUnorderAccessViewVariableByIndex(UINT idx, ID3D11UnorderedAccessView* pUAV)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectUnorderedAccessViewVariable* pVaiable = m_pEffect->GetVariableByIndex(idx)->AsUnorderedAccessView();
	if (!pVaiable->IsValid())
		return E_FAIL;
	return pVaiable->SetUnorderedAccessView(pUAV);
}
HRESULT CDXEffect::SetUnorderAccessViewVariableByName(const char* varName, CDXResource* pResource)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectUnorderedAccessViewVariable* pVaiable = m_pEffect->GetVariableByName(varName)->AsUnorderedAccessView();
	if (!pVaiable->IsValid())
		return E_FAIL;
	ID3D11UnorderedAccessView* pUAV = NULL;
	hr = pResource->GetUnorderedAccessView(NULL, &pUAV);
	if (FAILED(hr))
		return hr;
	hr = _StoreResourceByName(pResource, std::string(varName));
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	return pVaiable->SetUnorderedAccessView(pUAV);
}
HRESULT CDXEffect::SetUnorderAccessViewVariableBySemantic(const char* semantic, CDXResource* pResource)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectUnorderedAccessViewVariable* pVaiable = m_pEffect->GetVariableBySemantic(semantic)->AsUnorderedAccessView();
	if (!pVaiable->IsValid())
		return E_FAIL;
	ID3D11UnorderedAccessView* pUAV = NULL;
	hr = pResource->GetUnorderedAccessView(NULL, &pUAV);
	if (FAILED(hr))
		return hr;
	hr = _StoreResourceByName(pResource, std::string(semantic));
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	return pVaiable->SetUnorderedAccessView(pUAV);
}
HRESULT CDXEffect::SetUnorderAccessViewVariableByIndex(UINT idx, CDXResource* pResource)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectUnorderedAccessViewVariable* pVaiable = m_pEffect->GetVariableByIndex(idx)->AsUnorderedAccessView();
	if (!pVaiable->IsValid())
		return E_FAIL;
	ID3D11UnorderedAccessView* pUAV = NULL;
	hr = pResource->GetUnorderedAccessView(NULL, &pUAV);
	if (FAILED(hr))
		return hr;
	hr = _StoreResourceByIndex(pResource, idx);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	return pVaiable->SetUnorderedAccessView(pUAV);
}

HRESULT CDXEffect::SetUnorderAccessVieweArrayVariableByName(const char* varName, ID3D11UnorderedAccessView** ppUAV, UINT offset, UINT nElem)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectUnorderedAccessViewVariable* pVaiable = m_pEffect->GetVariableByName(varName)->AsUnorderedAccessView();
	if (!pVaiable->IsValid())
		return E_FAIL;
	return pVaiable->SetUnorderedAccessViewArray(ppUAV, offset, nElem);
}
HRESULT CDXEffect::SetUnorderAccessViewArrayVariableBySemantic(const char* semantic, ID3D11UnorderedAccessView** ppUAV, UINT offset, UINT nElem)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectUnorderedAccessViewVariable* pVaiable = m_pEffect->GetVariableBySemantic(semantic)->AsUnorderedAccessView();
	if (!pVaiable->IsValid())
		return E_FAIL;
	return pVaiable->SetUnorderedAccessViewArray(ppUAV, offset, nElem);
}
HRESULT CDXEffect::SetUnorderAccessViewArrayVariableByIndex(UINT idx, ID3D11UnorderedAccessView** ppUAV, UINT offset, UINT nElem)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectUnorderedAccessViewVariable* pVaiable = m_pEffect->GetVariableByIndex(idx)->AsUnorderedAccessView();
	if (!pVaiable->IsValid())
		return E_FAIL;
	return pVaiable->SetUnorderedAccessViewArray(ppUAV, offset, nElem);
}
HRESULT CDXEffect::SetUnorderAccessVieweArrayVariableByName(const char* varName, CDXResource** ppResource, UINT offset, UINT nElem)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectUnorderedAccessViewVariable* pVaiable = m_pEffect->GetVariableByName(varName)->AsUnorderedAccessView();
	if (!pVaiable->IsValid())
		return E_FAIL;
	ID3D11UnorderedAccessView** ppUAV = new ID3D11UnorderedAccessView*[nElem];
	std::vector<CDXResource*> resourceVec(nElem, NULL);
	for (UINT i=0; i < nElem; i++)
	{
		ID3D11UnorderedAccessView* pUAV = NULL;
		hr = ppResource[i]->GetUnorderedAccessView(NULL, &pUAV);
		if (FAILED(hr))
		{
			assert(0);
			SAFE_DELETE_ARRAY(ppUAV);
			return hr;
		}
		ppUAV[i] = pUAV;
		resourceVec[i] = ppResource[i];
	}
	hr = pVaiable->SetUnorderedAccessViewArray(ppUAV, offset, nElem);
	SAFE_DELETE_ARRAY(ppUAV);
	hr = _StoreResourceArrayByName(resourceVec, std::string(varName));
	return hr;
}
HRESULT CDXEffect::SetUnorderAccessViewArrayVariableBySemantic(const char* semantic, CDXResource** ppResource, UINT offset, UINT nElem)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectUnorderedAccessViewVariable* pVaiable = m_pEffect->GetVariableBySemantic(semantic)->AsUnorderedAccessView();
	if (!pVaiable->IsValid())
		return E_FAIL;
	ID3D11UnorderedAccessView** ppUAV = new ID3D11UnorderedAccessView*[nElem];
	std::vector<CDXResource*> resourceVec(nElem, NULL);
	for (UINT i=0; i < nElem; i++)
	{
		ID3D11UnorderedAccessView* pUAV = NULL;
		hr = ppResource[i]->GetUnorderedAccessView(NULL, &pUAV);
		if (FAILED(hr))
		{
			SAFE_DELETE_ARRAY(ppUAV);
			return hr;
		}
		ppUAV[i] = pUAV;
		resourceVec[i] = ppResource[i];
	}
	hr = pVaiable->SetUnorderedAccessViewArray(ppUAV, offset, nElem);
	SAFE_DELETE_ARRAY(ppUAV);
	hr = _StoreResourceArrayBySemantic(resourceVec, std::string(semantic));
	return hr;
}
HRESULT CDXEffect::SetUnorderAccessViewArrayVariableByIndex(UINT idx, CDXResource** ppResource, UINT offset, UINT nElem)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectUnorderedAccessViewVariable* pVaiable = m_pEffect->GetVariableByIndex(idx)->AsUnorderedAccessView();
	if (!pVaiable->IsValid())
		return E_FAIL;
	ID3D11UnorderedAccessView** ppUAV = new ID3D11UnorderedAccessView*[nElem];
	std::vector<CDXResource*> resourceVec(nElem, NULL);
	for (UINT i=0; i < nElem; i++)
	{
		ID3D11UnorderedAccessView* pUAV = NULL;
		hr = ppResource[i]->GetUnorderedAccessView(NULL, &pUAV);
		if (FAILED(hr))
		{
			assert(0);
			SAFE_DELETE_ARRAY(ppUAV);
			return hr;
		}
		ppUAV[i] = pUAV;
		resourceVec[i] = ppResource[i];
	}
	hr = pVaiable->SetUnorderedAccessViewArray(ppUAV, offset, nElem);
	SAFE_DELETE_ARRAY(ppUAV);
	hr = _StoreResourceArrayByIndex(resourceVec, idx);
	return hr;
}

HRESULT CDXEffect::SetConstBufferVariableByName(const char* varName, ID3D11Buffer* pBuf)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectConstantBuffer* pVaiable = m_pEffect->GetVariableByName(varName)->AsConstantBuffer();
	if (!pVaiable->IsValid())
		return E_FAIL;
	return pVaiable->SetConstantBuffer(pBuf);
}
HRESULT CDXEffect::SetConstBufferVariableBySemantic(const char* semantic, ID3D11Buffer* pBuf)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectConstantBuffer* pVaiable = m_pEffect->GetVariableBySemantic(semantic)->AsConstantBuffer();
	if (!pVaiable->IsValid())
		return E_FAIL;
	return pVaiable->SetConstantBuffer(pBuf);
}
HRESULT CDXEffect::SetConstBufferVariableByIndex(UINT idx, ID3D11Buffer* pBuf) 
{
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectConstantBuffer* pVaiable = m_pEffect->GetVariableByIndex(idx)->AsConstantBuffer();
	if (!pVaiable->IsValid())
		return E_FAIL;
	return pVaiable->SetConstantBuffer(pBuf);
}
HRESULT CDXEffect::SetConstBufferVariableByName(const char* varName, CDXBuffer* pBuf) 
{
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectConstantBuffer* pVaiable = m_pEffect->GetVariableByName(varName)->AsConstantBuffer();
	if (!pVaiable->IsValid())
		return E_FAIL;
	ID3D11Buffer* pDXBuf = pBuf->GetBuffer();
	if (pDXBuf == NULL)
		return E_FAIL;
	hr = _StoreResourceByName(pBuf, std::string(varName));
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	return pVaiable->SetConstantBuffer(pDXBuf);
}
HRESULT CDXEffect::SetConstBufferVariableBySemantic(const char* semantic, CDXBuffer* pBuf)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectConstantBuffer* pVaiable = m_pEffect->GetVariableBySemantic(semantic)->AsConstantBuffer();
	if (!pVaiable->IsValid())
		return E_FAIL;
	ID3D11Buffer* pDXBuf = pBuf->GetBuffer();
	if (pDXBuf == NULL)
		return E_FAIL;
	hr = _StoreResourceByName(pBuf, std::string(semantic));
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	return pVaiable->SetConstantBuffer(pDXBuf);
}
HRESULT CDXEffect::SetConstBufferVariableByIndex(UINT idx, CDXBuffer* pBuf)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectConstantBuffer* pVaiable = m_pEffect->GetVariableByIndex(idx)->AsConstantBuffer();
	if (!pVaiable->IsValid())
		return E_FAIL;
	ID3D11Buffer* pDXBuf = pBuf->GetBuffer();
	if (pDXBuf == NULL)
		return E_FAIL;
	hr = _StoreResourceByIndex(pBuf, idx);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	return pVaiable->SetConstantBuffer(pDXBuf);
}

HRESULT CDXEffect::SetTextureBufferVariableByName(const char* varName, ID3D11ShaderResourceView* pSRV)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectConstantBuffer* pVaiable = m_pEffect->GetVariableByName(varName)->AsConstantBuffer();
	if (!pVaiable->IsValid())
		return E_FAIL;
	return pVaiable->SetTextureBuffer(pSRV);
}
HRESULT CDXEffect::SetTextureBufferVariableBySemantic(const char* semantic, ID3D11ShaderResourceView* pSRV)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectConstantBuffer* pVaiable = m_pEffect->GetVariableBySemantic(semantic)->AsConstantBuffer();
	if (!pVaiable->IsValid())
		return E_FAIL;
	return pVaiable->SetTextureBuffer(pSRV);
}
HRESULT CDXEffect::SetTextureBufferVariableByIndex(UINT idx, ID3D11ShaderResourceView* pSRV)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectConstantBuffer* pVaiable = m_pEffect->GetVariableByIndex(idx)->AsConstantBuffer();
	if (!pVaiable->IsValid())
		return E_FAIL;
	return pVaiable->SetTextureBuffer(pSRV);
}
HRESULT CDXEffect::SetTextureBufferVariableByName(const char* varName, CDXTexture2D* pTexture)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectConstantBuffer* pVaiable = m_pEffect->GetVariableByName(varName)->AsConstantBuffer();
	if (!pVaiable->IsValid())
		return E_FAIL;
	ID3D11ShaderResourceView* pSRV = NULL;
	hr = pTexture->GetShaderResourceView(NULL, &pSRV);
	if (FAILED(hr))
		return hr;
	hr = _StoreResourceByName(pTexture, std::string(varName));
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	return pVaiable->SetTextureBuffer(pSRV);
}
HRESULT CDXEffect::SetTextureBufferVariableBySemantic(const char* semantic, CDXTexture2D* pTexture)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectConstantBuffer* pVaiable = m_pEffect->GetVariableByName(semantic)->AsConstantBuffer();
	if (!pVaiable->IsValid())
		return E_FAIL;
	ID3D11ShaderResourceView* pSRV = NULL;
	hr = pTexture->GetShaderResourceView(NULL, &pSRV);
	if (FAILED(hr))
		return hr;
	hr = _StoreResourceBySemantic(pTexture, std::string(semantic));
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	return pVaiable->SetTextureBuffer(pSRV);
}
HRESULT CDXEffect::SetTextureBufferVariableByIndex(UINT idx, CDXTexture2D* pTexture)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3DX11EffectConstantBuffer* pVaiable = m_pEffect->GetVariableByIndex(idx)->AsConstantBuffer();
	if (!pVaiable->IsValid())
		return E_FAIL;
	ID3D11ShaderResourceView* pSRV = NULL;
	hr = pTexture->GetShaderResourceView(NULL, &pSRV);
	if (FAILED(hr))
		return hr;
	hr = _StoreResourceByIndex(pTexture, idx);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	return pVaiable->SetTextureBuffer(pSRV);
}
HRESULT CDXEffect::_DispatchCS(ID3DX11EffectPass* pPass, UINT nThreadX, UINT nThreadY, UINT nThreadZ)
{
	if (pPass == NULL || m_pDevice == NULL)
		return E_FAIL;
	ID3D11DeviceContext* pDeviceContext = m_pDevice->GetD3D11DeviceContext();

	pPass->Apply(0, pDeviceContext);
	pDeviceContext->Dispatch(nThreadX, nThreadY, nThreadZ);

	//need to set the shader resource to NULL, or we will get a warning
	ID3D11ShaderResourceView *const pSRVNULL[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT] = {NULL};
	ID3D11UnorderedAccessView* const pUAVNULL[D3D11_PS_CS_UAV_REGISTER_COUNT] = {NULL};
	ID3D11Buffer* const pCSCBNULL[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT] = {NULL};
	UINT pUAVInitCount[D3D11_PS_CS_UAV_REGISTER_COUNT] = {0};
	pDeviceContext->CSSetShaderResources(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, pSRVNULL);
	pDeviceContext->CSSetUnorderedAccessViews(0, D3D11_PS_CS_UAV_REGISTER_COUNT, pUAVNULL, pUAVInitCount);
	return S_OK;
}
HRESULT CDXEffect::DispatchCSByName(const char* techName, const char* passName, UINT nThreadX, UINT nThreadY, UINT nThreadZ)
{
	if (m_pEffect == NULL)
		return E_FAIL;

	ID3DX11EffectTechnique* pTechnique = m_pEffect->GetTechniqueByName(techName);
	ID3DX11EffectPass* pPass = pTechnique->GetPassByName(passName);
	if (pTechnique == NULL || pPass == NULL)
		return E_FAIL;
	return _DispatchCS(pPass, nThreadX, nThreadY, nThreadZ);

}
HRESULT CDXEffect::DispatchCS(UINT idxTech, UINT idxPass, UINT nThreadX, UINT nThreadY, UINT nThreadZ)
{
	if (m_pEffect == NULL)
		return E_FAIL;
	
	ID3DX11EffectTechnique* pTechnique = m_pEffect->GetTechniqueByIndex(idxTech);
	ID3DX11EffectPass* pPass = pTechnique->GetPassByIndex(idxPass);
	if (pTechnique == NULL || pPass == NULL)
		return E_FAIL;
	return _DispatchCS(pPass, nThreadX, nThreadY, nThreadZ);
	
}

HRESULT CDXEffect::CalcDispatchThread(UINT& nTX, UINT& nTY, UINT& nTZ, UINT nNeedEntry, UINT nThreadInFX)
{
	
	UINT nNeedTreadGroup = ceil((float)nNeedEntry/ nThreadInFX);
	nTX = 1;
	nTY= 1;
	nTZ = 1;
	if (nNeedTreadGroup < 65535)
	{
		nTX = nNeedTreadGroup;
	}
	else if ( nNeedTreadGroup < 65535*65535)
	{
		nTX = ceil(sqrt((double)nNeedTreadGroup));
		nTY = nTX;
	}
	else 
	{
		nTX = ceil(pow(10, log((double)nNeedTreadGroup)/3.0));
		nTY = nTX;
		nTZ = nTX;
	}
	return S_OK;
}